﻿#include "FileTransfer.h"
#include <QFile>
#include <QFileInfo>
#include <QThread>
#include <QDir>

FileTransfer::FileTransfer(TransferProxy *proxy)
    :TransferBase(proxy) {

}

void FileTransfer::sendFile(QString filePath) {
    filePath = filePath.remove("file:///");
    //文件存在才发送 要不然不管
    if(QFile::exists(filePath)) {
        QFile file(filePath);
        //打开方式：只读
        if(!file.open(QIODevice::ReadOnly)) {
            return;
        }
        QByteArray byte = file.readAll();
        int size = byte.size();
        QString fileName = QFileInfo(filePath).fileName();
        QString head = transferPrefix();
        //如图片就是Image:@size:1024;fileName:guagua.png :@是INFOFLAG
        QString sendStr = QString("%1%2%size:%3;fileName:%4\n")
                .arg(head)
                .arg(INFOFLAG)
                .arg(size)
                .arg(fileName);

        qDebug() << "send str = " << sendStr;
        //发送图片大小和路径
        mTransproxy->getSocket()->write(sendStr.toStdString().c_str());
        //休眠20ms 防止碾包
        QThread::msleep(20);
        int totalSendSize = 0;
        while(totalSendSize < size) {
            int sendSize = 0;
            //如果总的字节减已经发送的总结书大于4096 说明还能发4096 所以继续发
            if(size - totalSendSize >= 4096) {
                sendSize = 4096;
            }else {
                //到这里说明已经发送的字节数离目标字节数小于4096了 所以看看还剩多少可以发
                sendSize = size - totalSendSize;
            }
            //指针不断的做偏移，一开始的时候 totalSendSize为0 所以指针是图标的第一个像素
            //第二次发送已经发了4096个字节了 所以要偏移4096个字节 其他依次如此
            //发送图片的数据
            mTransproxy->getSocket()->write((const char*)byte.data() + totalSendSize, sendSize);
            totalSendSize += sendSize;
            qDebug() << "alread send3" << totalSendSize;
        }
        qDebug() << "send over";
        //到这里说明发完了
    }
}

void FileTransfer::saveFile() {
    //GetSaveDir是虚函数，如果是Image 他返回的是Image保存的路径， 如果是Movie返回的就是movie的
    QString path = getSaveDir() + "/" + mSaveFileName;
    //如果打开了就写，没有打开就打开
    QFile fileObj(path);
    //以追加的方式写在文件末尾
    bool res = fileObj.open(QIODevice::WriteOnly | QIODevice::Append);
    qDebug() << "svae file = " << path << "res = " << res;
    if(!res) {
        return;
    }

    //到这里文件肯定是打开的
    uint bufferSize = mTransproxy->getSocket()->size();
    //还可以读取的字节数
    uint canReadSize = mReciveFilesize - mAlreadyReadFileSize;
    //如果可以读取的小于buffer里的，那么就读取剩余可读取的字节数
    qDebug() << "buffersize = " << bufferSize << "canReadSize = " <<canReadSize ;
    QByteArray readByte;
    if(canReadSize < bufferSize) {
        readByte = mTransproxy->getSocket()->read(canReadSize);
        mAlreadyReadFileSize += canReadSize;
    }else {
        //如果可以读取的大于buffer里的size 那么就全部读取
        readByte = mTransproxy->getSocket()->read(bufferSize);
        mAlreadyReadFileSize += bufferSize;
    }
    //读完就可以写，这样可以释放内存
    fileObj.write(readByte);
    //相等说明文件读完了 关闭file
    if(mAlreadyReadFileSize == mReciveFilesize) {
        mAlreadyReadFileSize = 0;
        fileObj.close();
        //读取完运行中状态变为false
        setRunningFlag(false);
        //调用子类实现的函数，这样子类就可以决定在文件保存完以后要干嘛了
        saveOverFunc();
    }
}

bool FileTransfer::praseHead(QString info) {
    //如图片就是Image:@size:1024;fileName:guagua.png :@是INFOFLAG
    //删除前面的Image:@
    info = info.remove(transferPrefix() +INFOFLAG);
    QStringList fileNameAndSize = info.split(";");
    if(fileNameAndSize.size() == 2) {
        QStringList sizeList     = fileNameAndSize.at(0).split(":");
        QStringList fileNameList = fileNameAndSize.at(1).split(":");
        if(sizeList.size() ==2 && fileNameList.size() == 2) {
            mReciveFilesize = sizeList.at(1).toUInt();
            mSaveFileName = fileNameList.at(1);
            qDebug() << "fileName = " << mSaveFileName << " size = " << mReciveFilesize;
            return true;
        }
    }
    //到这里说明解析失败
    return false;
}

bool FileTransfer::CheckPathIsExist(QString path, bool flag) {
    if(path.mid('/').size() <= 1) {
        return true;
    }
    QString dir = path.mid(0,path.lastIndexOf('/'));
    QDir Path;
    bool res = Path.exists(dir);
    qDebug() << "check Path: " << dir << path;
    if(!res && flag){
        //递归创建 因为如果是A/B/D文件夹，如果A不存在，BD都无法创建的
        CheckPathIsExist(dir, flag);
        Path.mkdir(dir);
        return true;
    }
    return res;
}

void FileTransfer::received(const QVariant &var)
{
    qDebug() << "fileTransfer var = " << var;
    //是否在接收中，如果是就继续保存文件任务 如果不是的话就要开始了
    if(isRunning()) {
        saveFile();
    }else {
        QString info = var.toString();
        //解析文件名和文件大小
        praseHead(info);
        if(mReciveFilesize > 0) {
            //开启任务
            setRunningFlag(true);
            saveFile();
        }
    }
}

